home *** CD-ROM | disk | FTP | other *** search
- /*------------------------------------------------------*/
- /* Factor the product N of two primes each of ≤ 32 bits */
- /*------------------------------------------------------*/
-
- #include "Factor64.h"
-
- /*------------------------------------------------------*/
- /* Factor64() is a simplified version of the quadratic */
- /* sieve using multiple polynomials */
- /*------------------------------------------------------*/
-
- void Factor64(ulong nL,ulong nH,ulong *p1,ulong *p2) {
-
- register ushort ls,k;
- register ulong i,j;
-
- ushort p,s,qi,hi,r,c,sP,sN;
- ushort ts,b,m,bm,br,m2,S[5];
- ulong d,e,sX,sQ,sq;
-
- Int B,C,Q,R,T,X,Y;
- ushort *Ptr,*pf,*sf,*lg,*r1,*r2;
- ushort *lv,**hm,*hp,**gm,*gp,*gi,*pv,**Xv,*Yv;
-
- /*------------------------------------------------------*/
- /* Check whether N is square */
- /*------------------------------------------------------*/
-
- N[1] = nL & 0xffff; N[2] = nL >> 16;
- N[3] = nH & 0xffff; N[4] = nH >> 16;
- k = 4; while (N[k] == 0) k--; N[0] = k;
-
- sq = floor(sqrt(nL + 4294967296.0*nH));
-
- Set(S,sq); Mul(S,S,S);
-
- if (Comp(S,N) == 0) {
- *p1 = sq;
- *p2 = sq;
- return;
- }
-
- /*------------------------------------------------------*/
- /* Check N for small factors (up to 0x800) */
- /*------------------------------------------------------*/
-
- for (k = 0; k < 616; k += 2) {
- p = Prm[k];
- if (Modq(N,p) == 0) {
- Divq(N,p);
- *p1 = p;
- *p2 = Unset(N);
- return;
- }
- }
-
- /*------------------------------------------------------*/
- /* Allocate memory */
- /*------------------------------------------------------*/
-
- Ptr = malloc(0x20000);
- if (Ptr == 0) {
- printf(" malloc failed \n");
- exit(0);
- }
- X = (ushort *) Ptr; Ptr += 20;
- Y = (ushort *) Ptr; Ptr += 20;
- B = (ushort *) Ptr; Ptr += 20;
- C = (ushort *) Ptr; Ptr += 20;
- Q = (ushort *) Ptr; Ptr += 20;
- R = (ushort *) Ptr; Ptr += 20;
- T = (ushort *) Ptr; Ptr += 20;
-
- pf = (ushort *) Ptr; Ptr += 120;
- sf = (ushort *) Ptr; Ptr += 120;
- lg = (ushort *) Ptr; Ptr += 120;
- r1 = (ushort *) Ptr; Ptr += 120;
- r2 = (ushort *) Ptr; Ptr += 120;
- lv = (ushort *) Ptr; Ptr += 12000;
-
- hm = (ushort **) Ptr; Ptr += 240;
- hm[0] = (ushort *) Ptr; Ptr += 14400;
- gm = (ushort **) Ptr; Ptr += 240;
- gm[0] = (ushort *) Ptr; Ptr += 24000;
-
- pv = (ushort *) Ptr; Ptr += 120;
- Yv = (ushort *) Ptr; Ptr += 120;
- Xv = (ushort **) Ptr; Ptr += 240;
- Xv[0] = (ushort *) Ptr;
-
- for (k = 1; k < 120; k++) {
- hm[k] = hm[k-1] + 120;
- gm[k] = gm[k-1] + 120 + k;
- Xv[k] = Xv[k-1] + 6;
- }
-
- /*------------------------------------------------------*/
- /* Parameters for the sieve : ts and qs are cutoffs */
- /* b is size of prime base and m2 is size of sieve */
- /*------------------------------------------------------*/
-
- k = Bitsize(N);
-
- b = 2 + (5*k)/4;
- bm = b + 3;
-
- if (k > 40) m = 50*k + 400;
- else m = 100*k - 1600;
- m2 = m + m;
-
- if (k > 40) ts = 196 + k/2;
- else ts = 11*k - 24 - (k*k)/8;
-
- sq = ceil(sqrt(sq/m));
-
- /*------------------------------------------------------*/
- /* Construct the prime base */
- /*------------------------------------------------------*/
-
- L0: k = 2;
- i = 0;
- while (k < b) {
- p = Prm[i];
- i++;
- s = Modq(N,p);
- if (qrs(s,p) == 1) {
- pf[k] = p;
- sf[k] = mrt(s,p);
- lg[k] = Prm[i];
- k++;
- }
- i++;
- }
- pf[1] = 2;
-
- /*------------------------------------------------------*/
- /* Construct quadratic polynomials as needed */
- /*------------------------------------------------------*/
-
- while (Prm[i] < sq) i += 2;
- hi = i;
- qi = 0;
-
- L1: do {if (hi < 616) sP = Prm[hi];
- else sP = npr(sP);
- while ((sP&3) == 1) {
- hi += 2;
- if (hi < 616) sP = Prm[hi];
- else sP = npr(sP);
- }
- sN = Modq(N,sP);
- hi += 2;
- } while (qrs(sN,sP) == -1);
-
- Set(T,sN);
- Dif(T,T,N);
- Divq(T,sP);
- d = Modq(T,sP);
- d *= sP;
- d += sN;
- sX = hrt(d,sP);
- Set(X,sX);
-
- e = (ulong) sP*sP;
- Set(B,e);
- Mulq(B,m); Dif(B,B,X);
- Mul(C,B,B); Dif(C,C,N);
- Divq(C,sP); Divq(C,sP);
-
- /*------------------------------------------------------*/
- /* Do the sieve for current polynomial */
- /*------------------------------------------------------*/
-
- if ((B[1] & 1) == 0) {i = 1; j = 0;}
- else {i = 0; j = 1;}
-
- if ((N[1] & 7) == 0) ls = 21;
- else if ((N[1] & 3) == 0) ls = 14;
- else ls = 7;
-
- while (i < m2) {
- lv[i] = ls; i += 2;
- lv[j] = 0; j += 2;
- }
-
- for (k = 2; k < b; k++) {
- p = pf[k];
- s = sf[k];
- e = sX % p;
- d = sP % p;
- d *= d;
- d %= p;
- d = inv(d,p);
-
- if (e < s) e += p;
- i = e-s;
- i *= d;
- i %= p;
- i = m-i;
- i %= p;
- r1[k] = i;
-
- j = e+s;
- j *= d;
- j %= p;
- j = m-j;
- j %= p;
- r2[k] = j;
-
- if (i > j) {
- e = i;
- i = j;
- j = e;
- }
-
- ls = lg[k];
- while (j < m2) {
- lv[i] += ls; i += p;
- lv[j] += ls; j += p;
- }
- if (i < m2) lv[i] += ls;
- }
-
- /*------------------------------------------------------*/
- /* Factor polynomial to find rows of matrix hm[qi,k] */
- /*------------------------------------------------------*/
-
- for (i = 0; i < m2; i++) if (lv[i] > ts) {
- hp = hm[qi];
- d = (ulong) i*sP;
- Set(T,d);
- Mul(Q,T,T); Add(Q,Q,C);
- R[0] = B[0]; R[1] = B[1];
- R[2] = B[2]; R[3] = B[3];
- s = i+i; Mulq(R,s);
- if (Comp(Q,R) == 1) hp[0] = 0;
- else hp[0] = 1;
- Dif(Q,Q,R);
-
- hp[1] = 0;
- while ((Q[1] & 1) == 0) {
- hp[1] += 1;
- Shiftr(Q);
- }
-
- k = b;
- while (Q[0] > 2) {
- k--;
- if (k == 1) goto L2;
- p = pf[k];
- j = i % p;
- if (j == r1[k] || j == r2[k]) {
- hp[k] = 1;
- Divq(Q,p);
- while (Modq(Q,p) == 0) {
- hp[k] += 1;
- Divq(Q,p);
- }
- }
- else hp[k] = 0;
- }
- sQ = Unset(Q);
- while (sQ > 1) {
- k--;
- if (k == 1) goto L2;
- p = pf[k];
- j = i % p;
- if (j == r1[k] || j == r2[k]) {
- hp[k] = 1;
- sQ /= p;
- while (sQ%p == 0) {
- hp[k] += 1;
- sQ /= p;
- }
- }
- else hp[k] = 0;
- }
-
- while (k > 2) {
- k--;
- hp[k] = 0;
- }
- Mulq(T,sP);
- Dif(Xv[qi],T,B);
- Yv[qi] = sP;
- qi += 1;
- if (qi == bm) goto L3;
- L2: ;
- }
- goto L1;
-
- /*------------------------------------------------------*/
- /* Row reduce gm = hm % 2 and find X^2 = Y^2 (mod N) */
- /*------------------------------------------------------*/
-
- L3: k = N[0];
- g = (double) N[k];
- if (d > 1) g += N[k-1]/65536.0;
- if (d > 2) g += N[k-2]/4294967296.0;
- if (d > 3) g += 1/4294967296.0;
-
- for (r = 0; r < bm; r++) {
- hp = hm[r]; gp = gm[r];
- for (c = 0; c < b; c++)
- gp[c] = hp[c] & 1;
- br = b + r;
- for (c = b; c < br; c++) gp[c] = 0;
- gp[br] = 1;
- }
-
- for (r = 0; r < bm; r++) {
- br = b + r;
- gp = gm[r];
-
- c = b - 1;
- while (gp[c] == 0 && c > 0) c--;
-
- if (c > 0 || gp[0] == 1) {
- for (i = r+1; i < bm; i++) {
- gi = gm[i];
- if (gi[c] == 1) {
- gi[c] = 0;
- for (k = 0; k < c ; k++)
- gi[k] ^= gp[k];
- for (k = b; k <= br; k++)
- gi[k] ^= gp[k];
- }
- }
- }
- else {
- for (i = 1; i < b; i++) pv[i] = 0;
-
- Set(X,1); Set(Y,1);
- for (k = b; k <= br; k++)
- if (gp[k] == 1) {
- j = k - b;
- Mul(X,X,Xv[j]);
- if (X[0] > 12) Mod(X);
- Mulq(Y,Yv[j]);
- if (Y[0] > 12) Mod(Y);
- for (i = 1; i < b; i++)
- pv[i] += (long) hm[j][i];
- }
- Mod(X);
-
- k = pv[1] >> 1;
- while (k > 15) {
- for (i = Y[0]; i > 0; i--)
- Y[i+1] = Y[i];
- Y[1] = 0;
- Y[0] += 1;
- k -= 16;
- if (Y[0] > 12) Mod(Y);
- }
- Mulq(Y,1 << k);
-
- for (i = 2; i < b; i++) {
- j = pv[i];
- if (j == 0) continue;
- if (j == 2) Mulq(Y,pf[i]);
- else {
- T[1] = pf[i];
- T[0] = 1;
- while (j > 2) {
- j -= 2;
- Mulq(T,pf[i]);
- }
- Mul(Y,Y,T);
- }
- if (Y[0] > 12) Mod(Y);
- }
- Mod(Y);
-
- Dif(T,X,Y);
- Add(R,X,Y);
- if (Comp(N,R) <= 0) Dif(R,R,N);
- if (T[0] == 0 || R[0] == 0) continue;
- *p1 = Gcd(T);
- *p2 = Gcd(R);
- return;
- }
- }
- bm += 5;
- ts -= 2;
- goto L0;
- }
-
- /*------------------------------------------------------*/
- /* End of the function Factor64(). */
- /*------------------------------------------------------*/
-
- /*------------------------------------------------------*/
- /* Inverse of b modulo m (Euclid’s algorithm) */
- /*------------------------------------------------------*/
-
- ulong inv(ulong b,ushort m) {
-
- register ulong u,v,t,n;
-
- u = 1;
- v = 0;
- t = 1;
- n = m;
-
- for (;;) {
- while ((b & 1) == 0) {
- v <<= 1;
- if (t & 1) t += m;
- t >>= 1;
- b >>= 1;
- }
- if (b == 1) break;
-
- if (b > n) {
- b -= n;
- u += v;
- }
- else {
- n -= b;
- v += u;
- }
-
- while ((n & 1) == 0) {
- u <<= 1;
- if (t & 1) t += m;
- t >>= 1;
- n >>= 1;
- }
- }
- t *= u;
- t %= m;
-
- return t;
- }
-
- /*------------------------------------------------------*/
- /* Determine if n is square modulo p (QR algorithm) */
- /*------------------------------------------------------*/
-
- short qrs(ushort n,ushort p) {
-
- register short j;
- register ushort n2,n4;
-
- if (n == 1) return 1;
-
- j = 1;
- for (;;) {
- n2 = n + n;
- n4 = n2 + n2;
- p %= n4;
- while (p > n) {
- if (n & 2) j = -j;
- if (p > n2) p -= n2;
- else p = n2 - p;
- }
- if (p == 1) return j;
- n %= p;
- if (n == 1) return j;
- }
- }
-
- /*------------------------------------------------------*/
- /* Square root of n modulo p */
- /*------------------------------------------------------*/
-
- ushort mrt(ushort n,ushort p) {
-
- register ulong q,s;
- register long x,u,v;
- ulong m;
- long t,r;
-
- if (n == 1) return 1;
- q = (p+1) >> 1;
-
- m = n;
- if ((q & 1) == 0) {
- q >>= 1;
- s = 1;
- while (q > 0) {
- if (q & 1) {
- s *= m;
- s %= p;
- }
- m *= m;
- m %= p;
- q >>= 1;
- }
- if (s+s > p) s = p-s;
- return s;
- }
-
- s = 0;
- t = n;
- while (qrs(t,p) == 1) {
- s += 1;
- t += 1-s-s;
- if (t%p == 0) {
- if (s+s > p) s = p-s;
- return s;
- }
- if (t < p) t += p;
- }
-
- q >>= 1;
- n = t;
- r = s;
- u = 1;
- v = 1;
- while (q > 0) {
- x = n*u;
- x %= p;
- x *= u;
- x %= p;
- t = r*r;
- t %= p;
- if (t >= x) x = t-x;
- else x = t-x+p;
- u *= r;
- u %= p;
- u += u;
- u %= p;
- r = x;
- if (q & 1) {
- x = n*u;
- x %= p;
- x *= v;
- x %= p;
- t = s*r;
- t %= p;
- if (t >= x) x = t-x;
- else x = t-x+p;
- v *= r;
- v %= p;
- v += s*u;
- v %= p;
- s = x;
- }
- q >>= 1;
- }
-
- if (s+s > p) s = p-s;
- return s;
- }
- /*------------------------------------------------------*/
- /* Square root of n modulo p^2 for p = 3 (mod 4) */
- /*------------------------------------------------------*/
-
- ulong hrt(ulong n,ushort p) {
-
- register ulong s,t,x,y;
- ulong m;
-
- m = n%p;
- s = m;
- y = 1;
- t = p-3;
- t >>= 2;
- while (t > 0) {
- if (t&1) {
- y *= s;
- y %= p;
- }
- s *= s;
- s %= p;
- t >>= 1;
- }
- x = m*y;
- x %= p;
-
- s = (ulong) p*p;
- t = x*x;
- if (n < t) n += s;
- n -= t;
- n /= p;
- n *= y;
- n %= p;
-
- t = p;
- t += 1;
- t >>= 1;
- n *= t;
- n %= p;
-
- n *= p;
- n += x;
- if (n+n > s) n = s-n;
- return n;
- }
-
- /*------------------------------------------------------*/
- /* Get next prime */
- /*------------------------------------------------------*/
-
- ushort npr(ushort p) {
-
- register ushort d,s,k;
-
- do {p += 2;
- s = floor(sqrt(p));
- k = 0;
- d = 3;
- while (d <= s) {
- if (p%d == 0) break;
- k += 2;
- d = Prm[k];
- }
- }
- while (d <= s);
- return p;
- }
-
- /*------------------------------------------------------*/
- /* Addition S = A + B */
- /*------------------------------------------------------*/
-
- void Add(Int S,Int A,Int B) {
-
- register ushort *pH, *pL;
- register ulong t;
- register ushort c,k;
- ushort s,dH,dL;
-
- if (A[0] > B[0] ) {
- pH = A; dH = A[0];
- pL = B; dL = B[0];
- }
- else {
- pH = B; dH = B[0];
- pL = A; dL = A[0];
- }
- if (dL == 0) {
- if (S != pH)
- for (k = 0; k <= dH; k++) S[k] = pH[k];
- return;
- }
-
- k = 0;
- c = 0;
- while (k < dL) {
- k++;
- t = (ulong) pH[k] + pL[k] + c;
- if (t >= 0x10000) {
- t -= 0x10000;
- c = 1;
- }
- else c = 0;
- S[k] = t;
- }
- while (c == 1 && k < dH) {
- k++;
- s = pH[k];
- if (s == 0xFFFF) {
- S[k] = 0;
- c = 1;
- }
- else {
- S[k] = s + 1;
- c = 0;
- }
- }
- while (k < dH) {
- k++;
- S[k] = pH[k];
- }
- if (c == 1) {
- dH += 1;
- S[dH] = 1;
- }
- S[0] = dH;
- }
-
- /*------------------------------------------------------*/
- /* Difference D = |A - B| */
- /*------------------------------------------------------*/
-
- void Dif(Int D,Int A,Int B) {
-
- register ushort *pH, *pL;
- register long t;
- register ushort c,k;
- ushort s,dH,dL;
- short e;
-
- k = A[0];
- if (k > B[0]) e = 1;
- else {
- if (k < B[0]) e = -1;
- else {
- while (A[k] == B[k] && k > 0) k--;
- if (k == 0) {
- D[0] = 0;
- return;
- }
- if (A[k] > B[k]) e = 1;
- else e = -1;
- }
- }
- if (e == 1) {
- pH = A; dH = A[0];
- pL = B; dL = B[0];
- }
- else {
- pH = B; dH = B[0];
- pL = A; dL = A[0];
- }
- if (dL == 0) {
- if (D != pH)
- for (k = 0; k <= dH; k++) D[k] = pH[k];
- return;
- }
-
- c = 0;
- k = 0;
- while (k < dL) {
- k++;
- t = (long) pH[k] - pL[k] - c;
- if (t < 0) {
- t += 0x10000;
- c = 1;
- }
- else c = 0;
- D[k] = t;
- }
- while (c == 1 && k < dH) {
- k++;
- s = pH[k];
- if (s == 0) {
- D[k] = 0xFFFF;
- c = 1;
- }
- else {
- D[k] = s - 1;
- c = 0;
- }
- }
- while (k < dH) {
- k++;
- D[k] = pH[k];
- }
- k = dH;
- while (D[k] == 0 && k > 0) k--;
- D[0] = k;
- }
-
- /*------------------------------------------------------*/
- /* Multiply P = A * B */
- /*------------------------------------------------------*/
-
- void Mul(Int P,Int A,Int B) {
-
- register ushort *pB;
- register ulong t;
- register ushort s,n,k;
- ushort d,j;
-
- if (A[0] == 0 || B[0] == 0) {
- P[0] = 0;
- return;
- }
- d = A[0] + B[0];
-
- for (k = 1; k <= d; k++) bufm[k] = 0;
-
- pB = B;
- j = 0;
- while (j < A[0]) {
- j++;
- s = A[j];
- k = 0;
- n = j;
- while (k < pB[0]) {
- k++;
- t = (ulong) s * pB[k];
- bufm[n] += t & 0xFFFF;
- n++;
- bufm[n] += t >> 16;
- }
- }
-
- k = 1;
- while (k < d) {
- t = bufm[k];
- bufm[k] = t & 0xFFFF;
- k++;
- bufm[k] += t >> 16;
- }
-
- if (bufm[d] == 0) d -= 1;
-
- for (k = 1; k <= d; k++) P[k] = bufm[k];
- P[0] = d;
- }
-
- /*------------------------------------------------------*/
- /* Quick multiply A = A * b */
- /*------------------------------------------------------*/
-
- void Mulq(Int A,ushort b) {
-
- register ushort *pA;
- register ulong t,w,c;
- register ushort d,k;
-
- d = A[0];
- if (d == 0) return;
-
- pA = A;
- if (b == 0) {
- pA[0] = 0;
- return;
- }
-
- c = 0;
- k = 0;
- while (k < d) {
- k++;
- t = (ulong) pA[k] * b;
- w = (t & 0xFFFF) + c;
- c = t >> 16;
- if (w >= 0x10000) {
- w -= 0x10000;
- c += 1;
- }
- pA[k] = w;
- }
- if (c > 0) {
- d += 1;
- pA[d] = c;
- }
- A[0] = d;
- }
-
- /*------------------------------------------------------*/
- /* Modulo R = R % N */
- /*------------------------------------------------------*/
-
- void Mod(Int R) {
-
- register ulong t;
- register long w;
- register ushort k,j;
- ushort d,n,tL,tH;
- ulong c;
- short e;
- double f;
-
- d = N[0];
- n = R[0];
-
- if (d > n) return;
-
- for (k = 1; k <= n; k++) buf[k] = R[k];
-
- while (n >= d) {
-
- f = buf[n]*65536.0;
- if (n > 1) f += buf[n-1];
- t = f/g;
-
- e = n - d;
- if (e > 0) {
- tL = t & 0xFFFF;
- tH = t >> 16;
- }
- else {
- tL = t >> 16;
- if (tL == 0) {
- if (t < 0xFFFF) break;
- else {
- k = d;
- while (buf[k] == N[k] && k > 0) k--;
- if (k > 0 && buf[k] < N[k]) break;
- tL = 1;
- }
- }
- tH = 0;
- e = 1;
- }
-
- c = 0;
- j = e;
- for (k = 1; k <= d; k++) {
- t = (ulong) N[k]*tL + c;
- w = (ulong) buf[j] - (t & 0xFFFF);
- t >>= 16;
- if (w < 0) {
- buf[j] = 0x10000 + w;
- t += 1;
- }
- else buf[j] = w;
- j++;
- w = (ulong) buf[j] - t;
- if (w < 0) {
- buf[j] = 0x10000 + w;
- c = 0x10000;
- }
- else {
- buf[j] = w;
- c = 0;
- }
- }
-
- if (tH > 0) {
- c = 0;
- j = e + 1;
- for (k = 1; k <= d; k++) {
- t = (ulong) N[k]*tH + c;
- w = (ulong) buf[j] - (t & 0xFFFF);
- t >>= 16;
- if (w < 0) {
- buf[j] = 0x10000 + w;
- t += 1;
- }
- else buf[j] = w;
-
- if (k == d) break;
- j++;
- w = (ulong) buf[j] - t;
- if (w < 0) {
- buf[j] = 0x10000 + w;
- c = 0x10000;
- }
- else {
- buf[j] = w;
- c = 0;
- }
- }
- }
- while (buf[n] == 0 && n > 0) n--;
- if (n == d && buf[d] < N[d]) break;
- }
-
- for (k = 1; k <= n; k++) R[k] = buf[k];
- R[0] = n;
- }
-
- /*------------------------------------------------------*/
- /* Quick modulo A = A % m */
- /*------------------------------------------------------*/
-
- ushort Modq(Int A,ushort m) {
-
- register ulong z,t;
- ushort n,e;
-
- n = A[0];
- if (n == 0) return 0;
-
- for (e = 1; e <= n; e++) buf[e] = A[e];
-
- while (n > 1) {
- e = n - 1;
- t = ((ulong) buf[n] << 16) + buf[e];
- z = t/m;
-
- t -= z*m;
- buf[e] = t;
- if (t == 0) do e--;
- while (buf[e] == 0 && e > 0);
- n = e;
- }
- return buf[1] % m;
- }
-
- /*------------------------------------------------------*/
- /* Quick divide A = A / m */
- /*------------------------------------------------------*/
-
- void Divq(Int A,ushort m) {
-
- register ulong z,t;
- ushort n,e;
-
- n = A[0];
- if (n == 0) return;
-
- for (e = 1; e <= n; e++) {
- buf[e] = A[e];
- A[e] = 0;
- }
-
- while (n > 1) {
- e = n - 1;
- t = ((ulong) buf[n] << 16) + buf[e];
- z = t/m;
-
- if (z < 0x10000) A[e] = z;
- else {
- A[e] = z & 0xFFFF;
- A[n] = z >> 16;
- }
-
- t -= z*m;
- buf[e] = t;
- if (t == 0) do e--;
- while (buf[e] == 0 && e > 0);
- n = e;
- }
-
- n = buf[1];
- if (n >= m) A[1] = n/m;
- if (A[A[0]] == 0) A[0] -= 1;
- }
-
- /*------------------------------------------------------*/
- /* Shift right X = X >> 1 */
- /*------------------------------------------------------*/
-
- void Shiftr(Int X) {
-
- register ulong t;
- register ushort i,j,c,d;
-
- d = X[0];
- if (d == 0) return;
-
- i = 0;
- j = 1;
- c = X[1] >> 1;
- while (j < d) {
- j++;
- t = (ulong) X[j] << 15;
- t += c;
- i++;
- X[i] = t & 0xFFFF;
- c = t >> 16;
- }
- if (c == 0) d -= 1;
- else X[d] = c;
- X[0] = d;
- }
-
- /*------------------------------------------------------*/
- /* Compare : {+1 0 -1} as {X > Y X == Y X < Y} */
- /*------------------------------------------------------*/
-
- short Comp(Int X,Int Y) {
-
- register ushort d;
-
- d = X[0];
-
- if (d > Y[0]) return 1;
- if (d < Y[0]) return -1;
-
- while (X[d] == Y[d] && d > 0) d--;
-
- if (d == 0) return 0;
- if (X[d] > Y[d]) return 1;
- return -1;
- }
-
- /*------------------------------------------------------*/
- /* Convert from unsigned long to Int */
- /*------------------------------------------------------*/
-
- void Set(Int X, ulong n) {
-
- if (n == 0) {
- X[0] = 0;
- return;
- }
- if (n < 0x10000) {
- X[0] = 1;
- X[1] = n;
- return;
- }
- X[0] = 2;
- X[1] = n & 0xffff;
- X[2] = n >> 16;
- }
-
- /*------------------------------------------------------*/
- /* Convert from Int to unsigned long */
- /*------------------------------------------------------*/
-
- ulong Unset(Int X) {
-
- register ulong n;
- register ushort d;
-
- d = X[0];
- if (d == 0) return 0;
- n = (ulong) X[1];
- if (d == 1) return n;
- return (n + ((ulong) X[2] << 16));
- }
-
- /*------------------------------------------------------*/
- /* Number of Bits in X */
- /*------------------------------------------------------*/
-
- ulong Bitsize(Int X) {
-
- register ushort d,t;
- register ulong n;
-
- d = X[0];
- if (d == 0) return 0;
-
- n = (ulong) d << 4;
- t = 0x8000;
- while ((t & X[d]) == 0) {
- n -= 1;
- t >>= 1;
- }
- return n;
- }
-
- /*------------------------------------------------------*/
- /* The greatest common divisor of A and N */
- /*------------------------------------------------------*/
-
- ulong Gcd(Int A) {
-
- register long k;
-
- for (k = 0; k < 5; k++) buf[k] = N[k];
-
- while ((A[1]&1) == 0) Shiftr(A);
-
- for (;;)
- switch (Comp(A,buf)) {
- case 1 : Dif(A,A,buf);
- while ((A[1]&1) == 0) Shiftr(A);
- break;
- case -1 : Dif(buf,buf,A);
- while ((buf[1]&1) == 0) Shiftr(buf);
- break;
- case 0 : return Unset(A);
- }
- }
-
- /*------------------------------------------------------*/
- /* End of file Factor64.c */
- /*------------------------------------------------------*/